// Copyright 2025 Laszlo Consulting Kft.
// SPDX-License-Identifier: Apache-2.0

import { createContext, createSignal, useContext, JSX, createMemo, onMount, onCleanup, createEffect } from "solid-js";
import type { ActiveFilter } from "../components/filterBar/FilterBar.tsx";

interface PaneFilterState {
  // Active filters for this pane
  activeFilters: ActiveFilter[];
  setActiveFilters: (filters: ActiveFilter[]) => void;
  // Whether the pane is still using its built-in default filters (no user/URL state yet)
  isUsingDefaultFilters: boolean;
  
  // Selected view for this pane
  selectedView: string;
  setSelectedView: (viewId: string) => void;
  
  // Filter history for back/forward navigation
  filterHistory: { filters: ActiveFilter[]; viewId: string }[];
  currentHistoryIndex: number;
  canGoBack: boolean;
  canGoForward: boolean;
  goBack: () => void;
  goForward: () => void;
  
  // Sorting state
  sortColumn: string | null;
  setSortColumn: (column: string | null) => void;
  sortAscending: boolean;
  setSortAscending: (ascending: boolean) => void;
  
  // Helper functions
  getResourceType: () => string | undefined;
  getNamespace: () => string | undefined;
}

const PaneFilterContext = createContext<PaneFilterState>();

// Default filters for new panes
export const DEFAULT_PANE_FILTERS: ActiveFilter[] = [
  { name: 'ResourceType', value: 'core/Pod' },
  { name: 'Namespace', value: 'all-namespaces' }
];

// Registry to track pane filter states for split operations
const paneFilterRegistry = new Map<number, () => ActiveFilter[]>();

// Registry to persist per‑pane filter history across route navigation
type PaneFilterHistoryState = {
  history: { filters: ActiveFilter[]; viewId: string }[];
  index: number;
  usingDefaultFilters: boolean;
  selectedViewId: string;
};

const paneFilterHistoryRegistry = new Map<number, PaneFilterHistoryState>();

export function registerPaneFilters(paneId: number, getFilters: () => ActiveFilter[]) {
  paneFilterRegistry.set(paneId, getFilters);
}

export function unregisterPaneFilters(paneId: number) {
  paneFilterRegistry.delete(paneId);
}

export function getPaneFilters(paneId: number): ActiveFilter[] {
  const getFilters = paneFilterRegistry.get(paneId);
  return getFilters ? getFilters() : [];
}

export function PaneFilterProvider(props: { 
  paneId: number;
  initialFilters?: ActiveFilter[];
  onStateChange?: (filters: ActiveFilter[]) => void;
  children: JSX.Element;
}) {
  const [activeFilters, setActiveFiltersInternal] = createSignal<ActiveFilter[]>(props.initialFilters || DEFAULT_PANE_FILTERS);
  const [selectedView, setSelectedView] = createSignal<string>('');
  const [filterHistory, setFilterHistory] = createSignal<{ filters: ActiveFilter[]; viewId: string }[]>([]);
  const [currentHistoryIndex, setCurrentHistoryIndex] = createSignal<number>(-1);
  const [navigatingHistory, setNavigatingHistory] = createSignal<boolean>(false);
  const [sortColumn, setSortColumn] = createSignal<string | null>(null);
  const [sortAscending, setSortAscending] = createSignal<boolean>(true);
  // Track whether we're still on the built-in defaults (no URL/cache/user interaction yet)
  const [usingDefaultFilters, setUsingDefaultFilters] = createSignal<boolean>(!props.initialFilters);

  // Restore history for this pane (if we have any saved state)
  const savedHistory = paneFilterHistoryRegistry.get(props.paneId);
  if (savedHistory && Array.isArray(savedHistory.history) && savedHistory.history.length > 0) {
    // Restore core signals without pushing new history entries
    const safeHistory = savedHistory.history.map(entry => ({
      filters: entry.filters.map(f => ({ ...f })),
      viewId: entry.viewId || ""
    }));
    setFilterHistory(safeHistory);
    setCurrentHistoryIndex(Math.min(
      Math.max(savedHistory.index, 0),
      safeHistory.length - 1
    ));
    setUsingDefaultFilters(savedHistory.usingDefaultFilters);
    const currentIdx = currentHistoryIndex();
    const currentState = safeHistory[currentIdx] ?? safeHistory[safeHistory.length - 1];
    if (currentState) {
      setActiveFiltersInternal(currentState.filters.map(f => ({ ...f })));
      setSelectedView(currentState.viewId || savedHistory.selectedViewId || "");
    }
  }

  // Register this pane's filter getter in the registry
  onMount(() => {
    registerPaneFilters(props.paneId, () => activeFilters());
  });

  // Clean up registry on unmount
  onCleanup(() => {
    unregisterPaneFilters(props.paneId);
  });

  // Notify parent of state changes
  createEffect(() => {
    const filters = activeFilters();
    props.onStateChange?.(filters);
  });

  // Helper to get resource type from active filters
  const getResourceType = () => {
    return activeFilters().find(f => f.name === "ResourceType")?.value;
  };

  // Helper to get namespace from active filters
  const getNamespace = () => {
    return activeFilters().find(f => f.name === "Namespace")?.value;
  };

  // Add to history when filters change
  const addToHistory = (filters: ActiveFilter[], viewId: string) => {
    if (navigatingHistory()) return; // Don't add to history when navigating

    const current = filterHistory();
    const currentIndex = currentHistoryIndex();
    
    // Remove any history after current index (when branching from middle of history)
    const newHistory = current.slice(0, currentIndex + 1);
    
    // Add new state to history
    newHistory.push({ filters: [...filters], viewId });
    
    // Keep history size reasonable (last 50 states)
    if (newHistory.length > 50) {
      newHistory.shift();
    } else {
      setCurrentHistoryIndex(currentIndex + 1);
    }
    
    setFilterHistory(newHistory);
  };

  // Custom setActiveFilters that manages history
  const setActiveFilters = (filters: ActiveFilter[]) => {
    setActiveFiltersInternal(filters);
    setUsingDefaultFilters(false);
    addToHistory(filters, selectedView());
  };

  const canGoBack = createMemo(() => currentHistoryIndex() >= 1);
  const canGoForward = createMemo(() => currentHistoryIndex() < filterHistory().length - 1);

  const goBack = () => {
    if (!canGoBack()) return;

    setNavigatingHistory(true);
    const newIndex = currentHistoryIndex() - 1;
    setCurrentHistoryIndex(newIndex);
    const historyState = filterHistory()[newIndex];
    setActiveFiltersInternal([...historyState.filters]);
    setSelectedView(historyState.viewId);
    setNavigatingHistory(false);
  };

  const goForward = () => {
    if (!canGoForward()) return;

    setNavigatingHistory(true);
    const newIndex = currentHistoryIndex() + 1;
    setCurrentHistoryIndex(newIndex);
    const historyState = filterHistory()[newIndex];
    setActiveFiltersInternal([...historyState.filters]);
    setSelectedView(historyState.viewId);
    setNavigatingHistory(false);
  };

  // Initialize history with initial filters
  onMount(() => {
    // Only seed history if we don't already have any entries (fresh pane)
    if (filterHistory().length === 0) {
      addToHistory(activeFilters(), selectedView());
    }
  });

  // Persist history state for this pane so it survives route changes
  createEffect(() => {
    const history = filterHistory();
    const index = currentHistoryIndex();
    const defaultFilters = usingDefaultFilters();
    const viewId = selectedView();

    paneFilterHistoryRegistry.set(props.paneId, {
      history: history.map(entry => ({
        filters: entry.filters.map(f => ({ ...f })),
        viewId: entry.viewId || ""
      })),
      index,
      usingDefaultFilters: defaultFilters,
      selectedViewId: viewId || ""
    });
  });

  const store: PaneFilterState = {
    get activeFilters() { return activeFilters(); },
    setActiveFilters,
    get isUsingDefaultFilters() { return usingDefaultFilters(); },
    get selectedView() { return selectedView(); },
    setSelectedView,
    get filterHistory() { return filterHistory(); },
    get currentHistoryIndex() { return currentHistoryIndex(); },
    get canGoBack() { return canGoBack(); },
    get canGoForward() { return canGoForward(); },
    goBack,
    goForward,
    get sortColumn() { return sortColumn(); },
    setSortColumn,
    get sortAscending() { return sortAscending(); },
    setSortAscending,
    getResourceType,
    getNamespace,
  };

  return (
    <PaneFilterContext.Provider value={store}>
      {props.children}
    </PaneFilterContext.Provider>
  );
}

export function usePaneFilterStore() {
  const context = useContext(PaneFilterContext);
  if (!context) {
    throw new Error("usePaneFilterStore must be used within a PaneFilterProvider");
  }
  return context;
}

